package com.aptemo.webetek.server.handlers;

import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import com.aptemo.webetek.client.commands.Action;
import com.aptemo.webetek.client.commands.impl.GetStatisticsAction;
import com.aptemo.webetek.client.commands.impl.GetStatisticsAction.EStatsPeriod;
import com.aptemo.webetek.client.enums.EnumEventStatus;
import com.aptemo.webetek.client.exceptions.BackendException;
import com.aptemo.webetek.client.exceptions.WebetekLoginException;
import com.aptemo.webetek.client.exceptions.BackendException.EErrorCodes;
import com.aptemo.webetek.server.StatisticsUserEngine;
import com.aptemo.webetek.server.data.Bet;
import com.aptemo.webetek.server.data.PMF;
import com.aptemo.webetek.server.data.UserGroup;
import com.aptemo.webetek.server.data.WebetekUser;
import com.aptemo.webetek.server.datastore.DataStoreAPI;
import com.aptemo.webetek.shared.StatisticsBean;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class GetStatisticsHandler
		extends ActionHandler<GetStatisticsAction, StatisticsBean>
{

	public GetStatisticsHandler(DataStoreAPI service)
	{
		super(service);
	}

	public Class<? extends Action<?>> getActionType()
	{
		return GetStatisticsAction.class;
	}

	@Override
	public StatisticsBean invoke(GetStatisticsAction action) throws BackendException, WebetekLoginException
	{
		StatisticsBean bean = null;
		switch (action.getTarget())
		{
			case EALL:
				bean = getAppStatistics(action.getPeriod());
				break;
			case ETEAM:
				bean = getTeamStatistics(action.getPeriod(), action.getTeamId());
				break;
			case EUSER:
				bean = getUserStatistics(action.getPeriod(), action.getTeamId());
				break;
		}
		return bean;
	}

	public StatisticsBean getAppStatistics(EStatsPeriod period)
	{
		StatisticsBean stats = new StatisticsBean();

		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			int noofusers = getNoOfUsers();

			Query query2 = pm.newQuery(Bet.class);
			query2.setFilter("status == statusParam && activeUntil == NULL");
			query2.declareParameters(EnumEventStatus.class.getName() + " statusParam");
			// query2.declareParameters("java.util.Date dateParam");
			List<Bet> bets = (List<Bet>) query2.execute(EnumEventStatus.ACTIVE);

			Query queryAllBets = pm.newQuery(Bet.class);
			List<Bet> allbets = (List<Bet>) queryAllBets.execute();

			Query query3 = pm.newQuery(UserGroup.class);
			List<UserGroup> teams = (List<UserGroup>) query3.execute();

			stats.setNoOfUsers(noofusers);
			stats.setNoOfTeams(teams.size());
			stats.setNoOfActiveBets(bets.size());
			stats.setNoOfAllBets(allbets.size());

			return stats;
		}
		finally
		{
			pm.close();
		}
	}

	public StatisticsBean getTeamStatistics(EStatsPeriod period, String teamid)
	{
		StatisticsBean stats = new StatisticsBean();

		stats.setNoOfUsers(getNoOfTeamUsers(teamid));

		return stats;
	}

	public StatisticsBean getUserStatistics(EStatsPeriod period, String teamid) throws WebetekLoginException, BackendException
	{

		// checkLogin();

		PersistenceManager pm = PMF.get().getPersistenceManager();

		try
		{
			Key key = KeyFactory.stringToKey(teamid);
			UserGroup team = pm.getObjectById(UserGroup.class, key);

			WebetekUser user = utils.getUser(pm, userService, team);
			if (user == null)
			{
				throw new BackendException(EErrorCodes.NOT_TEAM_MEMBER);
			}
			// TODO later calculate stats bean on login and pass the object...
			StatisticsUserEngine userStatistics = new StatisticsUserEngine(period, user.getSid());
			return userStatistics.calculate(pm, user);
		}
		finally
		{
			pm.close();
		}

	}

	private int getNoOfTeamUsers(String teamid)
	{
		int players = 0;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			Key key = KeyFactory.stringToKey(teamid);

			UserGroup team = pm.getObjectById(UserGroup.class, key);

			if (team != null)
			{
				team.getPlayers().size();
			}
			return players;
		}
		finally
		{
			pm.close();
		}
	}

	private int getNoOfUsers()
	{
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			Query query = pm.newQuery(WebetekUser.class);
			int users = ((List<WebetekUser>) query.execute()).size();

			return users;
		}
		finally
		{
			pm.close();
		}
	}
}
